//----------------------------------*-C++-*----------------------------------//
/*!
 * \file   Level_Symmetric_3D.hh
 * \author Jeremy Roberts
 * \date   06/19/2011
 * \brief  Level_Symmetric_3D class definition.  Derived from Denovo.
 * \note   Copyright (C) 2011 Jeremy Roberts
 */
//---------------------------------------------------------------------------//
// $Rev::                                               $:Rev of last commit
// $Author::                                            $:Author of last commit
// $Date::                                              $:Date of last commit
//---------------------------------------------------------------------------//

#ifndef LEVEL_SYMMETRIC_3D_HH
#define LEVEL_SYMMETRIC_3D_HH

#include <iostream>

#include "angle/Quadrature.hh"
#include "tran/Traits.hh"
#include "tran/Definitions.hh"

namespace slabtran
{

//===========================================================================//
/*!
 * \class Level_Symmetric_3D
 * \brief 2D/3D Level-symmetric (LQn) quadrature class.
 *
 * Level symmetric quadratures are characterized by using the same set of
 * \f$ N/2 \f$ positive values of the direction cosines with respect to
 * each of the axes.  There are \f$ N(N+2)/8 \f$ ordinates per octant,
 * yielding \f$ N(N+2) \f$ directions for a 3D problem.
 *
 * Not all the direction cosines are independent; for a given \f$ \mu_n \f$,
 * one has a single degree of freedom, e.g. one can further choose only
 * \f$ \eta_n \f$.  The final cosine is of course defined such that
 * the sum in quadrature is unity.
 *
 * An unfortunate aspect of LQn is that negative weights appear for
 * \f$ N = 20 \f$.  As an alternative, see the uniform and equal
 * weight quadrature set (UEn) \ref Uniform_Equal_3D, which yields positive
 * weights for arbitrarily high \f$ N \f$.
 *
 * \param sn_order   quadrature order
 * \param norm       normalization for weights
 * \param N          spatial dimension (default 3)
 *
 */
/*! 
 * \example test/testLevel_Symmetric_2D.cc
 *
 * Test of Level-Symmetric for 2D

 * \example test/testLevel_Symmetric_3D.cc
 *
 * Test of Level-Symmetric for 3D
 *
 */
//===========================================================================//

class Level_Symmetric_3D : public Quadrature<_3D>
{
  private:
    //! Base class typedef.
    typedef Quadrature<_3D> 			Base;
    typedef typename Base::Vec_Dbl 	    Vec_Dbl;
    int d_dimension;
  public:
    // Constructor.
    Level_Symmetric_3D(int sn_order, double norm);
    // Display the quadrature.
    //void display() const;
    void name() const{ std::cout << "Quadrature Type: Level_Symmetric_3D " << std::endl; };
  private:
    // hard coded tables of values of angles and weights
    friend void Set_Quad_Values( Vec_Dbl &att,
							     Vec_Dbl &wtt,
							   	 int levels,
								 int octantAngles );
    // helper init
    friend void Level_Symmetric_Init(const int &d_sn_order,
    		double    &d_norm,
    		int       &d_dimension,
    		Quadrature<_3D>::Angles 	 &d_angles,
    		Vec_Dbl &d_wt);

};

//===========================================================================//
/*!
 * \class Level_Symmetric_2D
 * \brief 2D Level-symmetric (LQn) quadrature class.
 *
 */
/*!
 * \example test/testLevel_Symmetric_2D.cc
 *
 * Test of Level-Symmetric for 2D
 *
 */
//===========================================================================//
class Level_Symmetric_2D : public Quadrature<_2D>
{
  private:
    //! Base class typedef.
    typedef Quadrature<_2D> 			Base;
    typedef typename Base::Vec_Dbl 	    Vec_Dbl;
    int d_dimension;
  public:
    // Constructor.
    Level_Symmetric_2D(int sn_order, double norm);
    // Display the quadrature.
    //void display() const;
    void name() const{ std::cout << "Quadrature Type: Level_Symmetric_2D " << std::endl; };
  private:
    // hard coded tables of values of angles and weights
    friend void Set_Quad_Values( Vec_Dbl &att,
							     Vec_Dbl &wtt,
							   	 int levels,
								 int octantAngles );
    // helper init
    friend void Level_Symmetric_Init(const int &d_sn_order,
    		double    &d_norm,
    		int       &d_dimension,
    		Quadrature<_3D>::Angles 	 &d_angles,
    		Vec_Dbl &d_wt ); // note, 2/3D have same angles);

};

// namespace declarations
void Set_Quad_Values( Vec_Dbl &att,
					  Vec_Dbl &wtt,
					  Vec_Dbl &d_wt,
					  int levels,
					  int octantAngles );
void Level_Symmetric_Init(const int &d_sn_order,
		double    &d_norm,
		int       &d_dimension,
		Quadrature<_3D>::Angles 	 &d_angles,
		Vec_Dbl &d_wt );

} // end namespace slabtran

#endif // LEVEL_SYMMETRIC_3D_HH

//---------------------------------------------------------------------------//
//              end of Level_Symmetric_3D.hh
//---------------------------------------------------------------------------//
